﻿package znet

import (
	"errors"
	"fmt"
	"net"
	"zxGoServer/zinterface"
)

type Connection struct {
	zinterface.IConnection

	TcpServer zinterface.IServer

	netData zinterface.INetConn
	// id
	ConnId uint32
	//
	isClosed bool
	// 无缓冲管道，用于读写
	msgChan chan []byte
	// 有缓冲管道，用于读写
	msgBuffChan chan []byte
	//告知该链接已经退出/停止的channel
	ExitBuffChan chan bool
}

func NewConnection(server zinterface.IServer, netData zinterface.INetConn, connId uint32) *Connection {
	//初始化Conn属性
	c := &Connection{
		TcpServer:   server,
		msgChan:     make(chan []byte),
		msgBuffChan: make(chan []byte),
		netData:     netData,
		ConnId:      connId,
	}

	c.TcpServer.GetConnMgr().Add(c)

	return c
}

/*写消息Goroutine， 用户将数据发送给客户端*/
func (conn *Connection) startWriter() {
	fmt.Println("[Writer Goroutine is running]")
	defer fmt.Println(conn.RemoteAddr().String(), "[Writer Goroutine is exit]")

	for {
		select {
		case msg := <-conn.msgChan:
			// 有数据要发送给客户端
			if _, err := conn.netData.Write(msg); err != nil {
				fmt.Println("Send Data error", err, ", Conn Writer exit")
				return
			}
		case data, ok := <-conn.msgBuffChan:
			if ok {
				if _, err := conn.netData.Write(data); err != nil {
					fmt.Println("Send Data error", err, ", Conn Writer exit")
					return
				}
			} else {
				fmt.Println("[msgBuffChan is Closed]")
				break
			}
		case <-conn.ExitBuffChan:
			return
		}
	}
}

/*读消息Goroutine，用于从客户端中读取数据*/
func (conn *Connection) startReader() {
	fmt.Println("[Reader Goroutine is running]")
	defer fmt.Println(conn.RemoteAddr().String(), "[Reader Goroutine exit]")
	defer conn.Stop()

	for {
		// 创建拆包解包对象
		dp := NewDataPack()

		// 读取客户端的MsgHead
		headData := make([]byte, dp.GetHeadLen())
		if _, err := conn.netData.ReadFull(headData); err != nil {
			fmt.Println("Read Head Data error", err, ", Conn Reader exit")
			break
		}
		// 拆包，得到msgId 和 DataLen 放在msg中
		msg, err := dp.Unpack(headData)
		if err != nil {
			fmt.Println("Unpack Data error", err, ", Conn Reader exit")
			break
		}

		// 根据 dataLen 读取data， 放到msg.Data 里
		var data []byte
		if msg.GetDataLen() > 0 {
			data = make([]byte, msg.GetDataLen())
			if _, err := conn.netData.ReadFull(data); err != nil {
				fmt.Println("Read Data error", err, ", Conn Reader exit")
				break
			}
		}
		msg.SetData(data)

		//req := Request{conn: conn, msg: msg}

	}
}

/*
Start 启动连接，让当前连接开始工作
*/
func (conn *Connection) Start() {

	//1 开启用户从客户端读取数据流程的Goroutine
	go conn.startReader()
	//2 开启用于写回客户端数据流程的Goroutine
	go conn.startWriter()
	//按照用户传递进来的创建连接时需要处理的业务，执行钩子方法
	conn.TcpServer.CallOnConnStart(conn)
}

// 停止连接，结束当前连接状态M
func (conn *Connection) Stop() {
	fmt.Println("[Stop Goroutine] ConnID = ", conn.ConnId)
	if conn.isClosed == true {
		return
	}
	conn.isClosed = true

	conn.TcpServer.CallOnConnStop(conn)

	conn.TcpServer.GetConnMgr().Remove(conn)

	conn.ExitBuffChan <- true

	close(conn.msgBuffChan)
	close(conn.msgChan)
	close(conn.ExitBuffChan)

	err := conn.netData.Close()
	if err != nil {
		return
	}
}

func (conn *Connection) SendMsg(msgId uint32, data []byte) error {
	if conn.isClosed == true {
		return errors.New("Connection is closed when send msg")
	}
	// 将data 封包，并发送
	dp := NewDataPack()
	msg, err := dp.Pack(NewMsgPackage(msgId, data))
	if err != nil {
		fmt.Println("Pack Data error", err, ", msgId = ", msgId)
		return err
	}

	conn.msgChan <- msg
	return nil
}

func (conn *Connection) SendBuffMsg(msgId uint32, data []byte) error {
	if conn.isClosed == true {
		return errors.New("Connection is closed when send buff msg")
	}
	dp := NewDataPack()
	msg, err := dp.Pack(NewMsgPackage(msgId, data))
	if err != nil {
		fmt.Println("Pack Data error", err, ", msgId = ", msgId)
		return err
	}
	conn.msgBuffChan <- msg
	return nil
}

//func (conn *Connection) GetTCPConnection() *net.TCPConn {
//	return conn.netData.getTcpConn()
//}

func (conn *Connection) GetConnId() uint32 {
	return conn.ConnId
}

func (conn *Connection) RemoteAddr() net.Addr {
	return conn.netData.RemoteAddr()
}
